﻿/*
 * Сделано в SharpDevelop.
 * Пользователь: Badanin M.V.
 * Дата: 21.06.2013
 * Время: 16:18
 * Проект: РПН Регион 2013
 * Распространяется под лицензией GPL v3
 */
using System;
using System.Collections.Generic;
using System.Drawing;

using System.Threading;
namespace Region
{
  /// <summary>
  /// Менеджер фоновых задач
  /// </summary>
  public class RegionTaskManager
  {
    public delegate void OnEndHandler(RegionTask Task);    
    Object _lock = new Object();
    Int32 ETask=0;
    Int32 NTask=0;
    Dictionary<Int32,RegionTask> Tasks = new Dictionary<Int32,RegionTask>();
    public event OnEndHandler OnEnd;
    public RegionTask CurrentTask()
    {
      lock(_lock)
      {
        for(;ETask<NTask;ETask++)
          if (Tasks.ContainsKey(ETask))
            break;
        if (Tasks.ContainsKey(ETask)) 
          return Tasks[ETask];
        else
          return null;
      }
    }
    int Add(RegionTask Task)
    {
      lock(_lock)
      {
        Int32 nTask = ++NTask;
        Tasks.Add(nTask,Task);
        return nTask;
      }      
    }
    bool Del(Int32 nTask)
    {
      lock(_lock)
      { 
        if (Tasks.ContainsKey(nTask))
          return Tasks.Remove(nTask);        
      }      
      return false;
    }
    public class RegionTask
    {
      Object _lock = new Object();      
      RegionTaskManager m_Manager;      
      public event OnEndHandler OnEnd;
      public Int32 m_nTask;
      public Int32 m_TaskValue;
      public Boolean Pause;
      public Int32 TaskValue{get{return m_TaskValue;} set{m_TaskValue=value;while(Pause) Thread.Sleep(1);}}
      public Int32 TaskMax;
      public String Name = "";
      public String StatusText = "";
      public Image Picture;
      Boolean m_Start;
      Exception m_exception = null;
      public delegate void Entry(RegionTask Task);
      public RegionTask(RegionTaskManager Manager)
      {
        m_Manager = Manager;
        m_nTask = m_Manager.Add(this);
        m_Start=false; 
      }
      public RegionTask(RegionTaskManager Manager, Entry E):this(Manager)
      {
        Start(E);
      }
      void Process(Entry E)
      { 
        lock(_lock)        
        {
          m_Start=true;
          try{E(this);}
          catch(Exception Exc) {m_exception=Exc;}
          finally
          {
            if (OnEnd!=null) OnEnd(this);
            m_Manager.Del(m_nTask);
            if (m_exception!=null) throw m_exception;
          }
        }
      }            
      public void Start(Entry E)
      {
        m_Start=false;
        ThreadPool.QueueUserWorkItem(new WaitCallback((O)=>{Process(E);}));   
      }
      public void End()
      {        
        while(!m_Start) Thread.Sleep(1);
        lock(_lock) {};
      }
    }  
  }  
}
